/***************************************************************************
 *   Copyright (C) 2008 by Eduardo Gurgel Pinho                            *
 *   edgurgel@gmail.com                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/

#include "raytracer_panel.h"

#include "raytracing/raytracer.h"
#include "photonmapping/photontracer.h"

#include <QLabel>
#include <QMouseEvent>
#include <QSpinBox>
#include <QCheckBox>
#include <QAction>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>

namespace Ui {

Raytracer_Panel::Raytracer_Panel(QWidget* _parent = 0,Sirat::Ray_Tracing::Raytracer* _raytracer = 0) : QWidget(_parent) , raytracer(_raytracer) , photon_mapping(false) {
	QVBoxLayout* panel = new QVBoxLayout();
				
	QLabel* depth_label = new QLabel(tr("Depth:"));
	depth_spinbox = new QSpinBox();;
	
	QHBoxLayout* depth_layout = new QHBoxLayout();
	depth_layout->addWidget(depth_label);
	depth_layout->addStretch();
	depth_layout->addWidget(depth_spinbox);
			
	direct_illumination_checkbox = new QCheckBox(tr("Direct Illumination"));
	direct_illumination_checkbox->setChecked(true);
	
	panel->addLayout(depth_layout);
	panel->addWidget(direct_illumination_checkbox);
	panel->addWidget(create_rendering_groupbox());
	panel->addWidget(create_montecarlo_groupbox());
	panel->addWidget(create_photon_mapping_groupbox());
	
	panel->addStretch();
		
	connect(depth_spinbox,SIGNAL(valueChanged(int)),this,SLOT(depth_changed(int)));
	connect(direct_illumination_checkbox,SIGNAL(stateChanged(int)),this,SLOT(direct_illumination_changed(int)));
		
	// Main layout
	setLayout(panel);
			
}

Raytracer_Panel::~Raytracer_Panel(void) { }

QSize Raytracer_Panel::minimumSizeHint() const {
	return QSize(250,300);
}

Sirat::Ray_Tracing::Raytracer* Raytracer_Panel::get_raytracer(void) const { 
	return raytracer;
}


Sirat::Photon_Mapping::Photontracer* Raytracer_Panel::get_photontracer(void) const { 
	if(photon_mapping == true && raytracer != 0) {
		return new Sirat::Photon_Mapping::Photontracer(raytracer->get_scene(),2,num_photons_spinbox->value());
	} else return 0;
}

unsigned int Raytracer_Panel::get_sample_photons(void) const {
	return sample_photons_spinbox->value();
}

void Raytracer_Panel::set_raytracer(Sirat::Ray_Tracing::Raytracer* _raytracer) {
	raytracer = _raytracer;
	if(raytracer != 0) {
		depth_spinbox->setValue(raytracer->get_depth());
		sample_rays_spinbox->setValue(raytracer->get_sample_rays());
		indirect_illumination_checkbox->setChecked(raytracer->get_indirect_illumination());
		direct_illumination_checkbox->setChecked(raytracer->get_direct_illumination());
		#ifdef _OPENMP
		parallel_checkbox->setChecked(raytracer->get_parallel());
		num_threads_spinbox->setValue(raytracer->get_threads());
		#endif
	}
}


void Raytracer_Panel::direct_illumination_changed(int _direct_illumination) {
	if(raytracer != 0) {
		raytracer->set_direct_illumination(_direct_illumination);
	}
}

void Raytracer_Panel::indirect_illumination_changed(int _indirect_illumination) {
	if(raytracer != 0) {
		raytracer->set_indirect_illumination(_indirect_illumination);
		raytracer->set_shadow_rays(shadow_rays_spinbox->value());
	}
}

void Raytracer_Panel::soft_shadow_changed(int _soft_shadow) {
	if(raytracer != 0) {
		raytracer->set_soft_shadow(_soft_shadow);
		raytracer->set_shadow_rays(shadow_rays_spinbox->value());
	}
}

void Raytracer_Panel::depth_changed(int _depth) {
	if(raytracer != 0) raytracer->set_depth(_depth);
}

void Raytracer_Panel::sample_rays_changed(int _sample_rays) {
	if(raytracer != 0) raytracer->set_sample_rays(_sample_rays);
}

void Raytracer_Panel::shadow_rays_changed(int _shadow_rays) {
	if(raytracer != 0) raytracer->set_shadow_rays(_shadow_rays);
}

void Raytracer_Panel::parallel_changed(int _parallel) {
	#ifdef _OPENMP
	if(raytracer != 0) raytracer->set_parallel(_parallel);
	#endif
}

void Raytracer_Panel::num_threads_changed(int _num_threads) {
	#ifdef _OPENMP
	if(raytracer != 0) raytracer->set_threads(_num_threads);
	#endif
}

void Raytracer_Panel::photon_mapping_changed(int _photon_mapping) { 
	photon_mapping = _photon_mapping;
}

QGroupBox* Raytracer_Panel::create_rendering_groupbox(void) {
	parallel_checkbox = new QCheckBox(tr("Parallel rendering"));	
	
	QHBoxLayout* num_threads_layout = new QHBoxLayout();
	QLabel* num_threads_label = new QLabel(tr("Number of Threads:"));
	num_threads_spinbox = new QSpinBox();;
	num_threads_spinbox->setRange(1,10);
	num_threads_spinbox->setValue(2);
	
	num_threads_layout->addWidget(num_threads_label);
	num_threads_layout->addStretch();
	num_threads_layout->addWidget(num_threads_spinbox);
		
	QVBoxLayout* rendering_layout = new QVBoxLayout();
	rendering_layout->addWidget(parallel_checkbox);
	rendering_layout->addLayout(num_threads_layout);
	
	QGroupBox* rendering_groupbox = new QGroupBox(tr("Rendering Process"),this);
	
	rendering_groupbox->setLayout(rendering_layout);
	
	connect(parallel_checkbox,SIGNAL(stateChanged(int)),this,SLOT(parallel_changed(int)));
	connect(num_threads_spinbox,SIGNAL(valueChanged(int)),this,SLOT(num_threads_changed(int)));
	
	#ifndef _OPENMP
	parallel_checkbox->setCheckable(false);
	num_threads_spinbox->setReadOnly(true);
	#endif
	
	return rendering_groupbox;
}
QGroupBox* Raytracer_Panel::create_montecarlo_groupbox(void) {
	indirect_illumination_checkbox = new QCheckBox(tr("Indirect Illumination"));
	indirect_illumination_checkbox->setChecked(false);
	
	QHBoxLayout* sample_rays_layout = new QHBoxLayout();
	QLabel* sample_rays_label = new QLabel(tr("Sample rays:"));
	sample_rays_spinbox = new QSpinBox();
	sample_rays_spinbox->setRange(0,5000);
	sample_rays_spinbox->setValue(250);
	
	sample_rays_layout->addWidget(sample_rays_label);
	sample_rays_layout->addStretch();
	sample_rays_layout->addWidget(sample_rays_spinbox);
	
	soft_shadow_checkbox = new QCheckBox(tr("Soft Shadow"));
	soft_shadow_checkbox->setChecked(false); 
	
	QHBoxLayout* shadow_rays_layout = new QHBoxLayout();
	QLabel* shadow_rays_label = new QLabel(tr("Shadow rays:"));
	shadow_rays_spinbox = new QSpinBox();
	shadow_rays_spinbox->setRange(1,5000);
	shadow_rays_spinbox->setValue(250);
	
	shadow_rays_layout->addWidget(shadow_rays_label);
	shadow_rays_layout->addStretch();
	shadow_rays_layout->addWidget(shadow_rays_spinbox);
	
	QVBoxLayout* montecarlo_layout = new QVBoxLayout();
	montecarlo_layout->addWidget(indirect_illumination_checkbox);
	montecarlo_layout->addLayout(sample_rays_layout);
	montecarlo_layout->addWidget(soft_shadow_checkbox);
	montecarlo_layout->addLayout(shadow_rays_layout);
	
	QGroupBox* montecarlo_groupbox = new QGroupBox(tr("Monte Carlo Ray Tracing"),this);
	
	montecarlo_groupbox->setLayout(montecarlo_layout);
	
	connect(indirect_illumination_checkbox,SIGNAL(stateChanged(int)),this,SLOT(indirect_illumination_changed(int)));
	connect(sample_rays_spinbox,SIGNAL(valueChanged(int)),this,SLOT(sample_rays_changed(int)));
	connect(soft_shadow_checkbox,SIGNAL(stateChanged(int)),this,SLOT(soft_shadow_changed(int)));
	connect(shadow_rays_spinbox,SIGNAL(valueChanged(int)),this,SLOT(shadow_rays_changed(int)));
	
	return montecarlo_groupbox;
	
}
QGroupBox* Raytracer_Panel::create_photon_mapping_groupbox(void) {
	photon_mapping_checkbox = new QCheckBox(tr("Photon Mapping"));	
	
	QHBoxLayout* num_photons_layout = new QHBoxLayout();
	QLabel* num_photons_label = new QLabel(tr("Photons to be emmited:"));
	num_photons_spinbox = new QSpinBox();
	num_photons_spinbox->setRange(0,999999);
	num_photons_spinbox->setValue(30000);
	
	num_photons_layout->addWidget(num_photons_label);
	num_photons_layout->addStretch();
	num_photons_layout->addWidget(num_photons_spinbox);
	
	QHBoxLayout* sample_photons_layout = new QHBoxLayout();
	QLabel* sample_photons_label = new QLabel(tr("Sample photons:"));
	sample_photons_spinbox = new QSpinBox();
	sample_photons_spinbox->setRange(0,10000);
	sample_photons_spinbox->setValue(100);
	
	sample_photons_layout->addWidget(sample_photons_label);
	sample_photons_layout->addStretch();
	sample_photons_layout->addWidget(sample_photons_spinbox);
	
	QVBoxLayout* photon_mapping_layout = new QVBoxLayout();
	photon_mapping_layout->addWidget(photon_mapping_checkbox);
	photon_mapping_layout->addLayout(num_photons_layout);
	photon_mapping_layout->addLayout(sample_photons_layout);
	
	
	QGroupBox* photon_mapping_groupbox = new QGroupBox(tr("Photon Mapping"),this);
	
	photon_mapping_groupbox->setLayout(photon_mapping_layout);
	
	connect(photon_mapping_checkbox,SIGNAL(stateChanged(int)),this,SLOT(photon_mapping_changed(int)));
	
	return photon_mapping_groupbox;
}

}
